package com.boil.qz.safekavass.filter;

import com.boil.qz.safekavass.model.LoginUser;
import com.boil.util.Constants;
import com.boil.util.Utils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Created by ChenYong on 2017-04-14.
 * <br>
 * 请求参数过滤器。
 * <br>
 * 此过滤器的作用如下：
 * <ol>
 * <li>如果是 Get 请求，那么，需要对请求参数值先进行 ISO-8859-1 编码，再进行 UTF-8 解码，防止中文乱码；</li>
 * <li>如果是 Post 请求，不会出现中文乱码；</li>
 * <li>剔除请求参数值的前后空格。</li>
 * </ol>
 */
public class RequestParamFilter implements Filter {
    /**
     * 日志
     */
    private static Logger log = LoggerFactory.getLogger(RequestParamFilter.class);
    /**
     * 编码格式
     */
    private String encoding = null;
    /**
     * 是否编码：
     * <ol>
     * <li>true-是；</li>
     * <li>false-否。</li>
     * </ol>
     */
    private boolean isEncoding = false;

    /**
     * 初始化。
     *
     * @param config 过滤器配置
     * @throws ServletException 抛出 ServletException
     */
    @Override
    public void init(FilterConfig config) throws ServletException {
        encoding = config.getInitParameter("encoding");

        String isEncodingTmp = config.getInitParameter("isEncoding");

        if (Constants.TRUE.equals(isEncodingTmp) || Constants.FALSE.equals(isEncodingTmp)) {
            isEncoding = Boolean.valueOf(isEncodingTmp);
        }
    }

    /**
     * 执行过滤。
     *
     * @param request  请求
     * @param response 响应
     * @param chain    过滤器链
     * @throws IOException      抛出 IOException
     * @throws ServletException 抛出 ServletException
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        chain.doFilter(new MyHttpServletRequestWrapper((HttpServletRequest) request), response);
    }

    /**
     * 销毁。
     */
    @Override
    public void destroy() {

    }

    /**
     * 我的 HttpServletRequestWrapper。
     *
     * @author ChenYong
     * @date 2017-04-20
     */
    private class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {
        /**
         * 请求
         */
        private HttpServletRequest request;
        /**
         * 获取登录用户
         */
        private LoginUser loginUser;
        /**
         * 账号
         */
        private String loginid;

        /**
         * 有参构造器。
         *
         * @param request 请求
         */
        public MyHttpServletRequestWrapper(HttpServletRequest request) {
            super(request);

            this.request = request;
            this.loginUser = (LoginUser) request.getSession().getAttribute(Constants.LOGIN_USER);

            if (loginUser == null) {
                this.loginid = "暂无";
            } else {
                this.loginid = loginUser.getLoginid();
            }
        }

        /**
         * 获取参数值。
         *
         * @param name 参数名称
         * @return 参数值
         */
        @Override
        public String getParameter(String name) {
            // 参数值
            String value = super.getParameter(name);

            // 如果是非 POST 请求
            if (isEncoding && !Constants.REQUEST_POST.equals(request.getMethod())) {
                value = Utils.decode(value, Constants.ISO_8859_1, encoding);
            }

            // 剔除前后空格
            value = StringUtils.trim(value);

            log.debug("账号：{}--->请求参数：{}-{}，", loginid, name, value);

            return value;
        }

        /**
         * 获取参数值数组。
         *
         * @param name 参数名称
         * @return 参数值数组
         */
        @Override
        public String[] getParameterValues(String name) {
            // 参数值
            String[] values = super.getParameterValues(name);

            if (values != null) {
                // 遍历参数值
                for (int i = Constants.VALUE_0; i < values.length; i++) {
                    // 参数值
                    String value = values[i];

                    // 如果是非 POST 请求
                    if (isEncoding && !Constants.REQUEST_POST.equals(request.getMethod())) {
                        value = Utils.decode(value, Constants.ISO_8859_1, encoding);
                    }

                    // 剔除前后空格
                    values[i] = StringUtils.trim(value);
                }
            }

            log.debug("账号：{}--->请求参数：{}-{}", loginid, name, Arrays.toString(values));

            return values;
        }

        /**
         * 获取参数名称与参数值的键值对。
         *
         * @return 参数名称与参数值的键值对
         */
        @Override
        public Map<String, String[]> getParameterMap() {
            // 获取所有请求参数键值对
            Map<String, String[]> paramMap = super.getParameterMap();

            if (paramMap != null) {
                paramMap = new HashMap<String, String[]>(paramMap);

                Iterator<Map.Entry<String, String[]>> paramIterator = paramMap.entrySet().iterator();

                while (paramIterator.hasNext()) {
                    // 参数键值对
                    Map.Entry<String, String[]> paramEntry = paramIterator.next();
                    // 旧参数值
                    String[] oldValues = paramEntry.getValue();
                    // 新参数值
                    String[] newValues = new String[oldValues.length];

                    // 遍历旧参数值
                    for (int i = Constants.VALUE_0; i < oldValues.length; i++) {
                        // 旧参数值
                        String value = oldValues[i];

                        // 如果是非 POST 请求
                        if (isEncoding && !Constants.REQUEST_POST.equals(request.getMethod())) {
                            value = Utils.decode(value, Constants.ISO_8859_1, encoding);
                        }

                        newValues[i] = StringUtils.trim(value);
                    }

                    paramMap.put(paramEntry.getKey(), newValues);
                }
            }

            log.debug("账号：{}--->请求参数：{}", loginid, paramMap);

            return paramMap;
        }
    }
}